#include "data/entry.h"
#include "database/connection.h"
#include "database/database.h"
#include "scanner/episode_name_parser.h"
#include "scanner/tv_processor.h"

namespace Tvimeg
{
	void TVProcessor::SetSeriesName(const std::string& name)
	{
		seriesName = name;
	}

	int TVProcessor::AddEntry(const Entry& entry) const
	{
		EpisodeNameParser parser;
		if (parser.Parse(entry.GetName()))
		{
			const int seriesID = GetSeriesID();
			const int seasonID = GetSeasonID(seriesID, parser.GetSeason());
			return GetEpisodeID(seriesID, seasonID, parser.GetEpisode());
		}

		return -1;
	}

	int TVProcessor::UpdateEntry(const Entry& entry) const
	{
		// call add entry to make sure the episode is in the db
		const int episodeID = AddEntry(entry);

		if (episodeID != -1)
		{
			// mark the episode for update
			Connection& connection = Database::GetInstance().GetConnection();
			connection.PrepareQuery("UPDATE tvEpisodes SET needsUpdate = 1 WHERE id = ?1;");
			connection.BindInt(1, episodeID);
			connection.ExecuteQuery();
		}

		return episodeID;
	}

	void TVProcessor::RemoveEntryFiles(const int entryId) const
	{
		Connection& connection = Database::GetInstance().GetConnection();
		connection.PrepareQuery("DELETE FROM tvEpisodeFiles WHERE episodeId = ?1;");
		connection.BindInt(1, entryId);
		connection.ExecuteQuery();
	}

	void TVProcessor::AddEntryFile(const int fileId, const int entryId) const
	{
		// add the link between the a file and a movie
		Connection& connection = Database::GetInstance().GetConnection();
		connection.PrepareQuery("INSERT INTO tvEpisodeFiles (episodeId, fileId) VALUES (?1, ?2);");
		connection.BindInt(1, entryId);
		connection.BindInt(2, fileId);
		connection.ExecuteQuery();
	}

	int TVProcessor::GetSeriesID(void) const
	{
		Connection& connection = Database::GetInstance().GetConnection();
		connection.PrepareQuery("SELECT id FROM tvShows WHERE lookupName = ?1;");
		connection.BindText(1, seriesName);
		if (connection.NextRow())
		{
			return connection.GetInt(0);
		}
		else
		{
			connection.PrepareQuery("INSERT INTO tvShows (lookupName, needsUpdate) VALUES (?1, 1);");
			connection.BindText(1, seriesName);
			connection.ExecuteQuery();
			return connection.GetLastId();
		}
	}

	int TVProcessor::GetSeasonID(const int seriesID, const int season) const
	{
		Connection& connection = Database::GetInstance().GetConnection();
		connection.PrepareQuery("SELECT id FROM tvSeasons WHERE tvShow = ?1 AND season = ?2;");
		connection.BindInt(1, seriesID);
		connection.BindInt(2, season);
		if (connection.NextRow())
		{
			return connection.GetInt(0);
		}
		else
		{
			connection.PrepareQuery("INSERT INTO tvSeasons (tvShow, season, needsUpdate) VALUES (?1, ?2, 1);");
			connection.BindInt(1, seriesID);
			connection.BindInt(2, season);
			connection.ExecuteQuery();
			return connection.GetLastId();
		}
	}

	int TVProcessor::GetEpisodeID(const int seriesID, const int seasonID, const int episode) const
	{
		Connection& connection = Database::GetInstance().GetConnection();
		connection.PrepareQuery("SELECT id FROM tvEpisodes WHERE tvShow = ?1 AND tvSeason = ?2 AND episode = ?3;");
		connection.BindInt(1, seriesID);
		connection.BindInt(2, seasonID);
		connection.BindInt(3, episode);
		if (connection.NextRow())
		{
			return connection.GetInt(0);
		}
		else
		{
			connection.PrepareQuery("INSERT INTO tvEpisodes (tvShow, tvSeason, episode, needsUpdate) VALUES (?1, ?2, ?3, 1);");
			connection.BindInt(1, seriesID);
			connection.BindInt(2, seasonID);
			connection.BindInt(3, episode);
			connection.ExecuteQuery();
			return connection.GetLastId();
		}
	}
}
